import run from './app/main'
import socket from "./app/socket";
import websocketIo from './app/until/websocket.io'
import dayjs from 'dayjs'
// 添加服务器websocket 功能
import SocketController from './app/controller/Socket.Controller'
import cluster from 'cluster'
import os from 'os'
const numCpu = os.cpus().length
import config from './config'
import {logger} from './app/until/log'
import TcpClient from './app/until/Tcp';
import { task } from "./app/task/monitDate"
import { initDatabase } from './app/until/context'
import type {IappPort} from './app/core/port.registry'
import { initSerialport,initSocket } from './app/core/initAppService';
import path from 'path'
import dotenv from 'dotenv'
import fs from 'fs-extra'

// 加载环境变量
dotenv.config()

// 初始化打包环境的目录结构
async function initPackagedEnvironment() {
    if ((process as any).pkg) {
        const configDir = path.join(process.cwd(), 'app', 'config');
        
        // 确保配置目录存在
        if (!fs.existsSync(configDir)) {
            fs.mkdirSync(configDir, { recursive: true });
            console.log('已创建配置目录:', configDir);
        }
        
        // 检查并创建 instance.json 文件
        const instanceJsonPath = path.join(configDir, 'instance.json');
        if (!fs.existsSync(instanceJsonPath)) {
            const defaultInstance = {
                database: {},
                nextInstanceNumber: 1
            };
            fs.writeJsonSync(instanceJsonPath, defaultInstance);
            console.log('已创建默认 instance.json 文件');
        }
        
        console.log('打包环境初始化完成');
    }
}

// 在应用启动前初始化环境
initPackagedEnvironment().catch(console.error);

// 优雅关闭函数
async function gracefulShutdown(reason: string, checkInterval?: NodeJS.Timeout) {

    logger.info(`开始优雅关闭，原因: ${reason}`);
    
    // 1. 清理定期检查任务
    if (checkInterval) {
        clearInterval(checkInterval);
    }
    
    // 2. 更改实例
    let instanceRegistryManager = (await import('./app/core/instance.registry')).default
    await instanceRegistryManager.getInstance.changeApplicationStatus(process.pid)

    // 3. 停止所有子进程
    for (const id in cluster.workers) {
        cluster.workers[id]?.kill();
    }
   
    
    // 4. 退出进程
    process.exit(0);
}

async function startServer() {
    // 获取实例数量限制
    const MAX_INSTANCE_NUM = parseInt(process.env.MAX_INSTANCE_NUM || '3');

    // 启动实例注册表管理器
    const instanceRegistryManager = (await import('./app/core/instance.registry')).default;
    const registryManager = instanceRegistryManager.getInstance;

    // 启动定期检查任务，每10秒检查一次实例状态
    const checkInterval = registryManager.startPeriodicCheck(10000);
    
    // 监测主进程监控
    try {
            // 启动全局注册表
            logger.info('='.repeat(50))
            logger.info('😊开启全局注册表')

            // 获取注册表管理器实例
            const registryManager = instanceRegistryManager.getInstance;
            
            // 先注册主进程实例
            const instanceName = await registryManager.registerApplication({
                pid: process.pid,
                lastUsed: dayjs().format('YYYY-MM-DD HH:mm:ss'),
                createdAt: dayjs().format('YYYY-MM-DD HH:mm:ss'),
                dataPath: '', // 将由registerApplication方法设置
                isActive: true,
                instanceId: 0 // 将由registerApplication方法设置
            });
            
            // 从注册表中获取已分配的端口
            const registry = await registryManager.readRegistryJson();
            const AppPort: IappPort = registry.database[instanceName].ports!;
            logger.info('='.repeat(50))
            logger.info('🛩️ 服务器使用已分配端口')
            logger.info(JSON.stringify(AppPort))
            logger.info('='.repeat(50))

            // 定时任务启动
            logger.info('='.repeat(50))
            logger.info('开启定时任务')
            task.start()

            // websocket服务器启动
            logger.info('='.repeat(50))
            logger.info('开启websocket服务器' + AppPort.websocketPort)
            websocketIo.getInstance.connection(AppPort.websocketPort)
            
            // 根据实例名称初始化数据库
            const dbPath = path.join(process.cwd(), 'app', 'config', instanceName + '.sqlite');
            logger.info(`数据库文件路径: ${dbPath}`);
            initDatabase(dbPath);// 启动子进程
            logger.info('='.repeat(50))
            logger.info(`Master ${process.pid} is running`)

            // 启动主进程的服务
            socket(AppPort.masterPort)

        if (config.method === "485通信") {
            logger.info('='.repeat(50))
            logger.info('🛩️服务器启动485通信')
            initSerialport(config,SocketController)
        } else {
             logger.info('='.repeat(50))
            logger.info('👌 服务器启动以太网通信')
             logger.info('='.repeat(50))
            initSocket(config,TcpClient.getInstance())
        }
        // 等待主进程实例完全初始化后再创建子进程
        logger.info('主进程实例初始化完成，准备创建Worker进程');
        
        // 检查实例数量限制并创建子进程
        if (numCpu > 1) {
            await createWorker(instanceName, AppPort, dbPath)
        } 
        
        cluster.on('exit', async (worker, code, signal) => {
            logger.info(`Worker ${worker.process.pid} died`);
            // 重新创建Worker进程时使用相同的实例信息
            await createWorker(instanceName, AppPort, dbPath)
        })

        process.on('uncaughtException', (err: any) => {
            logger.error('主进程发生未捕获的异常:', err);
            // 检查是否是磁盘空间不足的错误
            if (err.code === 'ENOSPC') {
                logger.fatal('检测到磁盘空间不足，系统将立即关闭以防止数据损坏。');
            }
            gracefulShutdown('主进程异常', checkInterval);
        });

    process.on('unhandledRejection', (reason, promise) => {
        logger.error('主进程发生未处理的Promise拒绝:', reason);
    });

    process.on('SIGINT', () => {
        logger.info('收到SIGINT信号，准备优雅关闭');
        gracefulShutdown('SIGINT', checkInterval);
    });

    process.on('SIGTERM', () => {
        logger.info('收到SIGTERM信号，准备优雅关闭');
        gracefulShutdown('SIGTERM', checkInterval);
    });

    // 添加更多的进程退出处理
    process.on('beforeExit', async (code) => {
        logger.info(`进程即将退出，退出码: ${code}`);
        try {
            const instanceRegistryManager = (await import('./app/core/instance.registry')).default;
            await instanceRegistryManager.getInstance.changeApplicationStatus(process.pid);
        } catch (err) {
            logger.error('在beforeExit中更新实例状态失败:', err);
        }
    });

    process.on('exit', (code) => {
        logger.info(`进程退出，退出码: ${code}`);
    });
    } catch(err) {
        logger.error(err)
    } 
}
async function createWorker(instanceName: string, appPort: IappPort, dbPath: string) {
    const worker = cluster.fork();
    
    // 监听Worker进程启动完成
    worker.on('online', () => {
        logger.info(`Worker ${worker.process.pid} 已上线，发送实例信息`);
        
        // 向Worker进程发送主进程的实例信息
        worker.send({
            type: 'INSTANCE_INFO',
            instanceName: instanceName,
            ports: appPort,
            dataPath: dbPath
        });
    });
    
    // worker.on('message', (msg) => {
    //     logger.info(`Worker ${worker.process.pid} 收到消息:`, msg);
    // });
    
    // worker.on('listening', () => {
    //     logger.info(`Worker ${worker.process.pid} 已启动并监听端口`);
    // });
}
// 主入口
if (cluster.isPrimary) {
    startServer()
} else {
    // Worker进程启动逻辑
    logger.info(`Worker 进程 ${process.pid} 启动，等待主进程实例信息`);
    
    // 设置超时，如果长时间没有收到实例信息则退出
    const timeout = setTimeout(() => {
        logger.error('Worker 进程超时未收到实例信息，退出');
        process.exit(1);
    }, 10000); // 10秒超时
    
    // 监听主进程发送的实例信息
    process.on('message', (msg: any) => {
        if (msg.type === 'INSTANCE_INFO') {
            // 清除超时器，因为已经收到实例信息
            clearTimeout(timeout);
            
            try {
                // 使用主进程传递的实例信息
                logger.info(`Worker 进程使用端口: ${msg.ports.childPort}`);
                
                // 初始化数据库连接（标记为Worker进程）
                initDatabase(msg.dataPath, true);
                
                // 启动Worker进程服务
                run(msg.ports.childPort);
                
            } catch (error) {
                logger.error('Worker 进程启动失败:', error);
                process.exit(1);
            }
        }
    });
}





